﻿using TencentCloud.Common;
using TencentCloud.Common.Profile;
using TencentCloud.Dnspod.V20210323;
using TencentCloud.Dnspod.V20210323.Models;

namespace xrwang.DDNS.TencentCloud
{
    /// <summary>
    /// 腾讯云域名记录操作
    /// </summary>
    public class DomainRecordOperator : IDomainRecordOperator
    {
        #region Const
        /// <summary>
        /// 默认的记录线路
        /// </summary>
        public const string DEFAULT_RECORD_LINE = "默认";
        #endregion Const

        /// <summary>
        /// 密匙id
        /// </summary>
        private string accessKeyID;
        /// <summary>
        /// 密匙id
        /// </summary>
        public string AccessKeyID
        {
            get
            {
                return accessKeyID;
            }
            set
            {
                if (string.IsNullOrWhiteSpace(value))
                    throw new ArgumentNullException(nameof(AccessKeyID), string.Format("{0}不能为空。", nameof(AccessKeyID)));
                accessKeyID = value;
                CreateClient();
            }
        }
        /// <summary>
        /// 密匙
        /// </summary>
        private string accessKeySecret;
        /// <summary>
        /// 密匙
        /// </summary>
        public string AccessKeySecret
        {
            get
            {
                return accessKeySecret;
            }
            set
            {
                if (string.IsNullOrWhiteSpace(value))
                    throw new ArgumentNullException(nameof(AccessKeySecret), string.Format("{0}不能为空。", nameof(AccessKeySecret)));
                accessKeySecret = value;
                CreateClient();
            }
        }
        /// <summary>
        /// 客户端
        /// </summary>
        private DnspodClient client;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="accessKeyID">密匙id</param>
        /// <param name="accessKeySecret">密匙</param>
        public DomainRecordOperator(string accessKeyID, string accessKeySecret)
        {
            if (string.IsNullOrWhiteSpace(accessKeyID))
                throw new ArgumentNullException(nameof(AccessKeyID), string.Format("{0}不能为空。", nameof(AccessKeyID)));
            this.accessKeyID = accessKeyID;
            if (string.IsNullOrWhiteSpace(accessKeySecret))
                throw new ArgumentNullException(nameof(AccessKeySecret), string.Format("{0}不能为空。", nameof(AccessKeySecret)));
            this.accessKeySecret = accessKeySecret;
            CreateClient();
        }

        /// <summary>
        /// 创建客户端
        /// </summary>
        private void CreateClient()
        {
            if (string.IsNullOrWhiteSpace(accessKeyID) || string.IsNullOrWhiteSpace(accessKeySecret))
                client = null;
            else
                client = new DnspodClient(new Credential()
                {
                    SecretId = accessKeyID,
                    SecretKey = accessKeySecret
                }, "");
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="recordId">记录id</param>
        /// <param name="domainName">域名</param>
        /// <returns>返回结果。如果成功，Data为请求id。</returns>
        public async Task<ActionResult<string>> DeleteAsync(string recordId, string domainName = "")
        {
            DeleteRecordRequest request = new DeleteRecordRequest();
            request.Domain = domainName;
            ulong id;
            if (!ulong.TryParse(recordId, out id))
                return new ActionResult<string>(false, "记录id无效。");
            request.RecordId = id;
            try
            {
                DeleteRecordResponse response = await client.DeleteRecord(request);
                return new ActionResult<string>(true, "", response.RequestId);
            }
            catch (TencentCloudSDKException e)
            {
                return new ActionResult<string>(false, e.Message, e.RequestId);
            }
            catch (Exception e)
            {
                return new ActionResult<string>(false, e.Message);
            }
        }

        /// <summary>
        /// 获取域名记录列表
        /// </summary>
        /// <param name="domainName">域名名称</param>
        /// <param name="rr">主机记录</param>
        /// <param name="type">记录类型</param>
        /// <param name="value">记录值</param>
        /// <param name="line">解析线路</param>
        /// <param name="page">页码</param>
        /// <param name="pageSize">每页记录数</param>
        /// <returns>返回结果。如果成功，Data1为域名记录信息列表，Data2为记录总数。</returns>
        public async Task<ActionResult<List<DomainRecordInfo>, int>> GetListAsync(string domainName, string rr = "", DomainRecordTypeEnum? type = null, string value = "", string line = "", int page = 1, int pageSize = 100)
        {
            DescribeRecordListRequest request = new DescribeRecordListRequest()
            {
                Domain = domainName,
                Subdomain = rr,
                RecordType = type.HasValue ? type.Value.ToString("g") : "",
                Keyword = value,
                RecordLine = line,
                Offset = (ulong)((page - 1) * pageSize),
                Limit = (ulong)pageSize
            };
            try
            {
                DescribeRecordListResponse response = await client.DescribeRecordList(request);
                return new ActionResult<List<DomainRecordInfo>, int>(true, "",
                    response.RecordList == null || response.RecordList.Length == 0 ? null : response.RecordList.Select(rec => new DomainRecordInfo()
                    {
                        RecordId = rec.RecordId.HasValue ? rec.RecordId.Value.ToString() : "",
                        DomainName = domainName,
                        RR = rec.Name,
                        Type = rec.Type,
                        Value = rec.Value,
                        TTL = (long?)rec.TTL,
                        Priority = (long?)rec.Weight,
                        Line = rec.Line,
                        Locked = string.IsNullOrWhiteSpace(rec.MonitorStatus) ? null : rec.MonitorStatus == "DOWN",
                        Status = rec.Status == DomainRecordStatusEnum.ENABLE.ToString("g")
                    }).ToList(),
                    response.RecordCountInfo.TotalCount.HasValue ? (int)response.RecordCountInfo.TotalCount.Value : 0);
            }
            catch (TencentCloudSDKException e)
            {
                return new ActionResult<List<DomainRecordInfo>, int>(false, e.Message, null, 0);
            }
            catch (Exception e)
            {
                return new ActionResult<List<DomainRecordInfo>, int>(false, e.Message, null, 0);
            }
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        /// <param name="recordId">记录id</param>
        /// <param name="domainName">域名名称</param>
        /// <returns>返回结果。如果成功，Data为请求id。</returns>
        public async Task<ActionResult<string>> SetStatusAsync(string recordId, string domainName = "", bool enabled = true)
        {
            ulong id;
            if (!ulong.TryParse(recordId, out id))
                return new ActionResult<string>(false, "记录id无效。");
            ModifyRecordStatusRequest request = new ModifyRecordStatusRequest()
            {
                Domain = domainName,
                RecordId = id,
                Status = (enabled ? DomainRecordStatusEnum.ENABLE : DomainRecordStatusEnum.DISABLE).ToString("g")
            };
            try
            {
                ModifyRecordStatusResponse response = await client.ModifyRecordStatus(request);
                return new ActionResult<string>(true, "", response.RequestId);
            }
            catch (TencentCloudSDKException e)
            {
                return new ActionResult<string>(false, e.Message, e.RequestId);
            }
            catch (Exception e)
            {
                return new ActionResult<string>(false, e.Message);
            }
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="record">域名记录</param>
        /// <returns>返回结果。如果成功，Data1为请求id，Data2为记录id。</returns>
        public async Task<ActionResult<string, string>> AddAsync(DomainRecordInfo record)
        {
            CreateRecordRequest request = new CreateRecordRequest()
            {
                Domain = record.DomainName,
                SubDomain = record.RR,
                RecordType = record.Type,
                RecordLine = string.IsNullOrWhiteSpace(record.Line) ? DEFAULT_RECORD_LINE : record.Line,
                Value = record.Value,
                TTL = (ulong?)record.TTL,
                Weight = (ulong?)record.Priority,
                Status = (record.Status ? DomainRecordStatusEnum.ENABLE : DomainRecordStatusEnum.DISABLE).ToString("g")
            };
            try
            {
                CreateRecordResponse response = await client.CreateRecord(request);
                return new ActionResult<string, string>(true, "", response.RequestId, response.RecordId.HasValue ? response.RecordId.Value.ToString() : null);
            }
            catch (TencentCloudSDKException e)
            {
                return new ActionResult<string, string>(false, e.Message, e.RequestId, null);
            }
            catch (Exception e)
            {
                return new ActionResult<string, string>(false, e.Message);
            }
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="record">域名记录</param>
        /// <returns>返回结果。如果成功，Data1为请求id，Data2为记录id。</returns>
        public async Task<ActionResult<string, string>> UpdateAsync(DomainRecordInfo record)
        {
            ulong id;
            if (!ulong.TryParse(record.RecordId, out id))
                return new ActionResult<string, string>(false, "记录id无效。");
            ModifyRecordRequest request = new ModifyRecordRequest()
            {
                Domain = record.DomainName,
                SubDomain = record.RR,
                RecordType = record.Type,
                RecordLine = string.IsNullOrWhiteSpace(record.Line) ? DEFAULT_RECORD_LINE : record.Line,
                Value = record.Value,
                TTL = (ulong?)record.TTL,
                Weight = (ulong?)record.Priority,
                Status = (record.Status ? DomainRecordStatusEnum.ENABLE : DomainRecordStatusEnum.DISABLE).ToString("g"),
                RecordId = id
            };
            try
            {
                ModifyRecordResponse response = await client.ModifyRecord(request);
                return new ActionResult<string, string>(true, "", response.RequestId, response.RecordId.HasValue ? response.RecordId.Value.ToString() : null);
            }
            catch (TencentCloudSDKException e)
            {
                return new ActionResult<string, string>(false, e.Message, e.RequestId, null);
            }
            catch (Exception e)
            {
                return new ActionResult<string, string>(false, e.Message);
            }
        }

        /// <summary>
        /// 保存
        /// </summary>
        /// <param name="record">域名记录</param>
        /// <returns>返回结果。如果成功，Data1为请求id，Data2为记录id。</returns>
        public async Task<ActionResult<string, string>> SaveAsync(DomainRecordInfo record)
        {
            ActionResult<List<DomainRecordInfo>, int> result = await GetListAsync(record.DomainName, record.RR);
            DomainRecordInfo rec = result.Success && result.Data1 != null ? result.Data1.FirstOrDefault(r => string.Compare(r.RR, record.RR, true) == 0) : null;
            if (rec != null)
            {
                record.RecordId = rec.RecordId;
                if (string.Compare(rec.Value, record.Value, true) != 0 || rec.Status != record.Status)
                    return await UpdateAsync(record);
                else
                    return new ActionResult<string, string>(true, "域名记录没有变化。");
            }
            else
                return await AddAsync(record);
        }
    }
}